package main

import (
	"net"
	"fmt"
	"os/exec"
	"os"
	"path/filepath"
	"net/http"
	"time"
	"io"
	"strconv"

	"github.com/gin-gonic/gin"
)

var port=":8086"//端口
var storage="./files"//上传文件目录
var currentDirectory string

func main() {
	//读取本地局域网IP
	interfaces,err:=net.Interfaces()
	if err !=nil{
		panic("Error : "+err.Error())
	}
	for _,inter:=range interfaces{
		temp,_:=inter.Addrs()
		for _,addr:=range temp{
			if addr.String() != "0.0.0.0" {
				fmt.Println("Server local Ip address:"+addr.String()+port)
			}
		}
	}
	//读取当前目录
	/*
	exec.LookPath:
	在环境变量PATH指定的目录中搜索可执行文件，如file中有斜杠，则只在当前目录搜索。
	返回完整路径或者相对于当前目录的一个相对路径。
	*/
	tempFile,_:=exec.LookPath(os.Args[0])
	currentDirectory=filepath.Dir(tempFile)
	//路由设置
	r:=gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.String(http.StatusOK,"pong")
	})
	r.Static("/html/static","./static")
	r.Static("/files","./files")
	r.GET("/", func(c *gin.Context) {
		c.File("html/up.html")
	})
	r.GET("/list", UpList)
	r.POST("/file",Upload)
	//启动服务
	s:=&http.Server{
		Addr:port,
		Handler:r,
		ReadTimeout:3600*time.Second,
		WriteTimeout:3600*time.Second,
		MaxHeaderBytes:1<<20,
	}
	s.ListenAndServe()
}

type DeleteFiles struct {
	FileName []string `json:"filename" binding:"required"`
}

type ListFiles struct {
	Name string `json:"name"`
	Size string `json:"size"`
}

func Upload(c *gin.Context)  {
	c.Request.ParseMultipartForm(32<<20)//在使用r.MultipartForm前必须先调用ParseMultipartForm方法，参数为最大缓存
	if c.Request.MultipartForm!=nil&&c.Request.MultipartForm.File!=nil {
		os.Chdir(storage)//进入存储目录
		defer os.Chdir(currentDirectory)//退出存储目录
		fhs:=c.Request.MultipartForm.File["userfile"]//获取所有上传文件信息
		num:=len(fhs)
		fmt.Printf("总文件数：%d 个文件",num)
		//循环对每个文件进行处理
		for n,fheader:=range fhs{
			//设置文件名
			newFileName:=fheader.Filename
			//打开上传文件
			uploadFile,err:=fheader.Open()
			if err!=nil {
				fmt.Println(err)
				c.String(http.StatusBadRequest,"上传文件失败",err.Error())
				return
			}
			defer uploadFile.Close()
			//保存文件
			saveFile,err:=os.Create(newFileName)
			if err !=nil{
				fmt.Println(err)
				c.String(http.StatusBadRequest,"上传失败",err.Error())
				return
			}
			defer saveFile.Close()
			io.Copy(saveFile,uploadFile)
			//获取文件状态信息
			fileStat,_:=saveFile.Stat()
			//打印接收信息
			fmt.Printf("%s No.:%d Size:%d KB Name:%s\n",time.Now().Format("2006-01-02 15:04:05"),n,fileStat.Size()/1024,newFileName)
		}
		c.String(http.StatusOK,"上传成功")
	}
}

func UpList(c *gin.Context)  {
	lm := make([]ListFiles, 0)
	//遍历目录，读出文件名、大小
	filepath.Walk(storage, func(path string, fi os.FileInfo, err error) error {
		if nil == fi {
			return err
		}
		if fi.IsDir() {
			return nil
		}
		//	fmt.Println(fi.Name(), fi.Size()/1024)
		var m ListFiles
		m.Name = fi.Name()
		m.Size = strconv.FormatInt(fi.Size()/1024, 10)
		lm = append(lm, m)
		return nil
	})
	//返回目录json数据
	c.JSON(http.StatusOK, lm)
}